<!--
  图片上传
  属性:
    - files { array } 默认展示的图片列表, 格式为: [{ name: 'test.png', url: '' }]
    - limit { number } 最大允许上传个数，默认为: 5个
    - maxFileSize { number } 支持可上传的最大文件大小，单位为: MB; 默认为: 5MB
    - disabled { boolean } 是否禁用
    - multiple { boolean } 是否支持多选文件
    - showTip { boolean } 是否显示提示说明文字
  使用方式:
    <base-image-upload :files="fileList"></base-image-upload>
-->
<template>
  <div class="base-image-upload" :class="{ 'is-disabled': disabled }">
    <el-upload
      action="."
      accept=".png,.jpg,.jpeg,.gif,.webp,.bmp"
      list-type="picture-card"
      :limit="limit"
      :multiple="multiple"
      :file-list="fileList"
      :disabled="disabled"
      :before-upload="onBeforeUpload"
      :before-remove="beforeRemove"
      :http-request="handleUploadFile"
      :on-remove="handleRemove"
      :on-exceed="handleExceed"
    >
      <div v-if="showTip" slot="tip">只能上传 {{tipExpandedNameStr}} 图片，且不超过 {{ maxFileSize }}MB</div>
      <div slot="default" class="upload-icon">
        <i class="el-icon-plus"></i><span>上传图片</span>
      </div>

      <div slot="file" slot-scope="{ file }">
        <img class="el-upload-list__item-thumbnail" :src="file.url" alt="">
        <span class="el-upload-list__item-actions">
          <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
            <i class="el-icon-zoom-in"></i>
          </span>
          <span v-if="download" class="el-upload-list__item-delete" @click="handleDownload(file)">
            <i class="el-icon-download"></i>
          </span>
          <span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemove(file)">
            <i class="el-icon-delete"></i>
          </span>
        </span>
      </div>
    </el-upload>

    <el-dialog width="720px" :visible.sync="dialogVisible" :close-on-click-modal="false" append-to-body modal-append-to-body destroy-on-close>
      <img width="100%" :src="dialogImageUrl" alt="">
    </el-dialog>
  </div>
</template>

<script>
export default {
  name: 'base-image-upload',
  props: {
    files: {
      type: Array,
      default: () => [],
    },
    // 最大允许上传个数
    limit: {
      type: Number,
      default: 5,
    },
    // 支持可上传的最大文件大小，单位为: MB; 默认为: 5MB
    maxFileSize: {
      type: Number,
      default: 5,
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      default: false,
    },
    // 是否支持多选文件
    multiple: {
      type: Boolean,
      default: true,
    },
    // 是否显示提示说明文字
    showTip: {
      type: Boolean,
      default: false,
    },
    // 是否显示下载
    download: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      fileList: [],
      dialogImageUrl: '',
      dialogVisible: false,
      tipExpandedNameStr: 'png/jpg/jpeg/gif/webp/bmp',
    };
  },
  watch: {
    files: {
      handler(newVal) {
        if (newVal) {
          this.fileList = newVal.map(file => ({ name: file.fileName, ...file }));
        } else {
          this.fileList = [];
        }
      },
      immediate: true,
      deep: true,
    },
  },
  methods: {
    /**
     * 是否符合定义的可上传最大文件大小的限制，默认为：5MB
     */
    isLimitSize(fileSize) {
      return fileSize / 1024 / 1024 < (this.maxFileSize || 5);
    },

    /**
     * 图片上传前的钩子函数
     * @description  支持的文件格式：.png,.jpg,.jpeg,.gif,.webp,.bmp
     */
    onBeforeUpload(file) {
      // 最大支持上传文件大小为 5MB
      const isLimitSize = this.isLimitSize(file.size);
      const extensionName = file.name.substring(file.name.lastIndexOf('.') + 1);
      const isPng = extensionName === 'png';
      const isJpg = extensionName === 'jpg';
      const isJpeg = extensionName === 'jpeg';
      const isGif = extensionName === 'gif';
      const isWebp = extensionName === 'webp';
      const isBmp = extensionName === 'bmp';

      if (!isPng && !isJpg && !isJpeg && !isGif && !isWebp && !isBmp) {
        this.$message.error('上传图片必须是 png/jpg/jpeg/gif/webp/bmp 格式!');
      }

      if (!isLimitSize) {
        this.$message.error(`上传图片大小不能超过 ${this.maxFileSize}MB!`);
      }

      return (isPng || isJpg || isJpeg || isGif || isWebp || isBmp) && isLimitSize;
    },

    /**
     * 删除前的钩子函数
     * @param file 文件对象
     */
    beforeRemove(file) { 
      const extensionName = file.name.substring(file.name.lastIndexOf('.') + 1);
      if(this.tipExpandedNameStr.split('/').includes(extensionName)){
        return this.$confirm(`确定移除 ${file.name}？`);
      }
    },

    /**
     * 删除文件
     * @param file
     */
    handleRemove(file) {
      this.beforeRemove(file).then(() => {
        if(this.fileList.findIndex(d => d.id === file.id)>=0){
          this.fileList.splice(this.fileList.findIndex(d => d.id === file.id), 1);
          this.$emit('upload', this.fileList);
        }
      }).catch(() => {});
    },

    /**
     * 自定义文件上传
     */
    handleUploadFile(result) {
      const file = result.file;
      // 最大支持上传文件大小为 5MB
      const isLimitSize = this.isLimitSize(file.size);
      if (!isLimitSize) {
        this.$message.error(`上传图片大小不能超过 ${this.maxFileSize}MB!`);
        return false;
      }

      const formData = new FormData();
      formData.append('file', file);

      this.$api.common.file.upload(formData).then(res => {
        this.$message.success('上传成功!');
        this.fileList.push({ name: res.fileName, url: res.filePath, ...res });
        this.$emit('upload', this.fileList);
      }).catch(err => {
        this.$message.error(err.data.message);
      });
    },

    handleExceed(files, fileList) {
      this.$message.warning(
        `当前限制选择 ${this.limit} 个文件，本次选择了 ${files.length} 个文件，共选择了 ${files.length + fileList.length} 个文件`,
      );
    },

    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url;
      this.dialogVisible = true;
    },

    handleDownload(file) {
      this.$api.common.file.download(file.id, file.fileName);
    },
  },
};
</script>

<style lang="scss" scoped>
.base-image-upload {
  &.is-disabled {
    .upload-icon {
      cursor: not-allowed;
    }
  }

  ::v-deep .el-upload--picture-card {
    width: 96px;
    height: 96px;
    line-height: 94px;

    &:hover {
      .el-icon-plus {
        color: #409EFF;
      }
    }
  }

  ::v-deep .el-upload-list--picture-card {
    .el-upload-list__item {
      width: 96px;
      height: 96px;
    }

    .el-upload-list__item-actions {
      font-size: 16px;
    }
  }

  .upload-icon {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    position: relative;
    overflow: hidden;

    .el-icon-plus {
      position: absolute;
      top: 50%;
      margin-top: -28px;
    }

    > span {
      font-size: 12px;
      transform: translateY(14px);
    }
  }
}
</style>
